package demo.xml.jaxen;

import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.jaxen.BaseXPath;
import org.jaxen.JaxenException;
import org.jaxen.XPath;
import org.jaxen.dom.DOMXPath;
import org.junit.jupiter.api.Assertions;
import org.w3c.dom.Element;

import com.titan.core.utils.data.AssertUtils;
import com.titan.core.utils.debug.Timer;
import com.titan.core.utils.io.ConsoleUtils;

public class BaseXPathTest {
    private void run() throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        org.w3c.dom.Document doc = factory.newDocumentBuilder().newDocument();
        DocumentBuilder builder = factory.newDocumentBuilder();
        
        testSelectSingleNodeForContext();
        testParentOfSelection();
        testEvaluateString();
        testNumberValueOfEmptyNodeSetIsNaN();
        testPathWithParentheses();
    }
    
    
    public void testPathWithParentheses() throws Exception {
        org.w3c.dom.Document doc = createDocument();
        Element root = doc.createElement("root");
        doc.appendChild(root);
        Element child = doc.createElement("child");
        root.appendChild(child);
        
        BaseXPath xpath = new DOMXPath("(/root)/child");
        Assertions.assertEquals(child, xpath.selectSingleNode(doc));
    }    
    public void testNumberValueOfEmptyNodeSetIsNaN() throws Exception {
        org.w3c.dom.Document doc = createDocument();
        BaseXPath xpath = new DOMXPath("/x");
        doc.appendChild(doc.createElement("root"));
        Double numberValue = (Double) xpath.numberValueOf(doc);
        Assertions.assertTrue(numberValue.isNaN());
        
    }
    public void testEvaluateString() throws Exception {
        org.w3c.dom.Document doc = createDocument();
        BaseXPath xpath = new DOMXPath("string(/*)");
        doc.appendChild(doc.createElement("root"));
        String stringValue = (String) xpath.evaluate(doc);
        Assertions.assertEquals("", stringValue);
        
    }    
    private void testParentOfSelection() throws Exception {
        /*
        html
            a
                img
            a        <- return that node
                img   <- select this node
        */
        org.w3c.dom.Document doc = createDocument();
        org.w3c.dom.Element html = doc.createElementNS("", "html");
        org.w3c.dom.Element a1 = doc.createElementNS("", "a");
        org.w3c.dom.Element a2 = doc.createElementNS("", "a");
        org.w3c.dom.Element img1 = doc.createElementNS("", "img");
        org.w3c.dom.Attr img1_src = doc.createAttributeNS("", "src");
        img1_src.setValue("1.gif");
        org.w3c.dom.Element img2 = doc.createElementNS("", "img");
        org.w3c.dom.Attr img2_src = doc.createAttributeNS("", "src");
        img2_src.setValue("2.gif");

        doc.appendChild(html);
        html.appendChild(a1);
        html.appendChild(a2);
        img1.setAttributeNode(img1_src);
        img2.setAttributeNode(img2_src);
        a1.appendChild(img1);
        a2.appendChild(img2);

        XPath xpath = new DOMXPath("(/html/a/img[contains(@src,'gif')])[2]/..");
        List result = xpath.selectNodes(doc);
        Assertions.assertEquals(1, result.size());
        Assertions.assertEquals(a2, result.get(0));
    }    
    private void testSelectSingleNodeForContext() throws JaxenException {
        BaseXPath xpath = new DOMXPath("1 + 2");
        String stringValue = xpath.stringValueOf(xpath);
        Assertions.assertEquals("3", stringValue);
        Number numberValue = xpath.numberValueOf(xpath);
        Assertions.assertEquals(3, numberValue.doubleValue(), 0.00001);
    }
    
    
    private org.w3c.dom.Document createDocument() throws ParserConfigurationException {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        org.w3c.dom.Document doc = factory.newDocumentBuilder().newDocument();
        return doc;
    }
    
    
    
    public static void main(String[] args) {
        Timer timer = Timer.$();
        try {
            BaseXPathTest test = new BaseXPathTest();
            test.run();
        } catch (Exception e) {
            e.printStackTrace();
            timer.print("执行总用时");
        }
    }
}
